package controllers;

import java.awt.geom.AffineTransform;
import java.awt.image.AffineTransformOp;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.logging.Level;
import play.*;
import play.mvc.*;

import java.util.*;
import sun.misc.BASE64Encoder;
import java.io.File;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import javax.imageio.ImageIO;
import models.*;
import org.apache.commons.io.IOUtils;
import play.db.jpa.Blob;
import play.libs.Files;
import play.libs.MimeTypes;

public class Photos extends Controller {
	
	public static void uploadUserPhoto() throws FileNotFoundException, IOException {
		String filename = params.get("qqfile");
		if (Login.isLoggedIn()) {
			User user = Login.getCurrentUser();
			user.distroyPhotoTmp();
			user.photoTmp = new Blob();
			user.photoTmp.set(request.body, MimeTypes.getContentType(filename));	
			BufferedImage before = ImageIO.read(user.photoTmp.get());
			BufferedImage after = scaleBufferedImageInFrame(before);
			ByteArrayOutputStream os = new ByteArrayOutputStream();
			ImageIO.write(after, "png", os);
			InputStream is = new ByteArrayInputStream(os.toByteArray());
			user.photoTmpThumbnail = new Blob();
			user.photoTmpThumbnail.set(is, MimeTypes.getContentType("a.png"));			
			user.save();
			renderJSON("{\"success\":true,\"w\":"+after.getWidth()+",\"h\":"+after.getHeight()+"}");
		} else {
			renderJSON("{\"error\":\"NEED LOGIN\"}");
		}
		
	}
	
	public static BufferedImage scaleBufferedImageInFrame(BufferedImage before) {
		float scaleRate;
		float beforeW = (float)(before.getWidth());
		float beforeH = (float)(before.getHeight());
		float MAXW = 750.0f;
		float MAXH = 550.0f;
		if(MAXH/beforeH > MAXW/beforeW) {
			scaleRate = MAXW/beforeW;
		} else {
			scaleRate = MAXH/beforeH;
		}
//		AffineTransform tx = new AffineTransform();
//		tx.scale(scaleRate, scaleRate);
//		AffineTransformOp op = new AffineTransformOp(tx, AffineTransformOp.TYPE_BILINEAR);
//		BufferedImage after = op.filter(before, null);
//		return after;
		return scaleBufferedImageByRatio(before, scaleRate);
	}
	
	public static BufferedImage scaleBufferedImageByRatio(BufferedImage before, float scaleRate) {
		AffineTransform tx = new AffineTransform();
		tx.scale(scaleRate, scaleRate);
		AffineTransformOp op = new AffineTransformOp(tx, AffineTransformOp.TYPE_BILINEAR);
		BufferedImage after = op.filter(before, null);
		return after;
	}
	
	public static void userHasPhoto(Long id) {
		final User user = User.findById(id);
		if (user != null) {
			renderJSON(user.hasPhoto());
		}
		renderJSON("NO USER");
	}
	
	public static void displayUserPhoto(long id, int size) {
		final User user = User.findById(id);

		if(size == 0) {
			response.setContentTypeIfNotSet(user.photo.type());
			renderBinary(user.photo.get());
		} else if(size == 50) {
			if(!user.hasPhotoThumbnail()) {
				response.setContentTypeIfNotSet(user.photo.type());
				renderBinary(user.photo.get());
			} else {
				response.setContentTypeIfNotSet(user.photoThumbnail.type());
				renderBinary(user.photoThumbnail.get());
			}
		}
	}
	
	public static void displayUserPhoto(long id) {
		displayUserPhoto(id, 50);
	}
	
	public static void displayUserPhotoThumbnail(long id) {
		final User user = User.findById(id);
		//if (user != null) {
			//if(user.hasPhoto()) {
		response.setContentTypeIfNotSet(user.photoTmpThumbnail.type());
		renderBinary(user.photoTmpThumbnail.get());
			//} 
		//} 
	}
	
	public static void displayCirclePhoto(long id) {
		final Circle circle = Circle.findById(id);
		response.setContentTypeIfNotSet(circle.photo.type());
		renderBinary(circle.photo.get());
	}

	public static void cropUserPhoto(Long uid, int x, int y, int w, int h) throws IOException {
		if(w <= 0 || h <=0) {
			renderJSON("{\"error\":\"invalid scale\"}");
		}
		User user = User.findById(uid);
		if(Login.isLoggedIn() && session.get("uid").equals(uid.toString())) {
			BufferedImage photo = ImageIO.read(user.photoTmp.get());
			BufferedImage photoThumbnail = ImageIO.read(user.photoTmpThumbnail.get());
			float scaleRate = ((float)photo.getWidth()) / ((float)photoThumbnail.getWidth());
			int rx = (int)((float)x * scaleRate);
			int ry = (int)((float)y * scaleRate);
			int rw = (int)((float)w * scaleRate);
			int rh = (int)((float)h * scaleRate);
			
			BufferedImage subPhoto = photo.getSubimage(rx, ry, rw, rw); // change rh -> rw to make it square
			subPhoto = scaleBufferedImageByRatio(subPhoto,180.0f/(float)rw);
			BufferedImage subPhotoThumbnail = scaleBufferedImageByRatio(subPhoto,50.0f/(float)(subPhoto.getWidth()));
			
			// save photo
			ByteArrayOutputStream os = new ByteArrayOutputStream();
			ImageIO.write(subPhoto, "png", os);
			InputStream is = new ByteArrayInputStream(os.toByteArray());
			user.distroyPhoto();
			user.photo = new Blob();
			user.photo.set(is, MimeTypes.getContentType("a.png"));
			
			// save photoThumbnail
			ByteArrayOutputStream os2 = new ByteArrayOutputStream();
			ImageIO.write(subPhotoThumbnail, "png", os2);
			InputStream is2 = new ByteArrayInputStream(os2.toByteArray());
			// we just distroy photo & its thumbnail
			user.photoThumbnail = new Blob();
			user.photoThumbnail.set(is2, MimeTypes.getContentType("a.png"));
			
			user.save();
			renderJSON("{\"success\":true}");
		} else {
			renderJSON("{\"error\":\"NEED LOGIN\"}");
		}
		
	}
	
//	public static String encryptImageName(String name) {
//		String encryptName = (new BASE64Encoder()).encode(name.getBytes());
//		return encryptName;
//	}
	
//	public static void changeImageName() {
//		/*String curDir = System.getProperty("user.dir");
//		System.out.println(curDir);*/
//		String name = params.get("n");
//		
//		String directory = "public/images/";
//		String newName = encryptImageName(name);
//		File original = new File(directory + name);
//		
//		if(!original.exists()) {
//			renderJSON(false);
//		}
//		
//		File newFile = new File(directory + newName);
//		if(original.renameTo(newFile)) {
//			renderJSON(true);
//		}
//		else {
//			renderJSON(false);
//		}
//	}

}